#cnt：给定日期（天, day.csv）时间（每小时,hour.csv）总租车人数，响应变量y
#casual、registered和cnt三个特征均为要预测的y（cnt =casual+registered ），作业里只需对cnt进行预测。
#批改标准
#1.对数据做数据探索分析（可参考EDA_BikeSharing.ipynb，不计分）
#2. 适当的特征工程（可参考FE_BikeSharing.ipynb，不计分）
#3. 对全体数据，随机选择其中80%做训练数据，剩下20%为测试数据，评价指标为RMSE。（10分）
#4. 用训练数据训练最小二乘线性回归模型（20分）、岭回归模型、Lasso模型，其中岭回归模型（30分）和Lasso模型（30分），注意岭回归模型和Lasso模型的正则超参数调优。
#5. 比较用上述三种模型得到的各特征的系数，以及各模型在测试集上的性能。并简单说明原因。（10分）

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
import os

from sklearn.linear_model import LinearRegression
from sklearn.linear_model import Ridge
from sklearn.linear_model import RidgeCV
from sklearn.linear_model import Lasso
from sklearn.linear_model import ElasticNet

from sklearn.metrics import r2_score  # R square
from sklearn.metrics import mean_squared_error  # 均方误差
from sklearn.metrics import mean_absolute_error  # 平方绝对误差




def Data_preprocessing():
    # 读入数据
    train = pd.read_csv("day.csv")
    # 对类别型特征预处理
    categorical_features = ['season', 'mnth', 'weathersit', 'weekday']
    # 数据类型变为object，才能被get_dummies处理
    for col in categorical_features:
        train[col] = train[col].astype('object')  # 数据类型转换
    print(train.head())
    X_train_cat = train[categorical_features]
    X_train_cat = pd.get_dummies(X_train_cat)
    # print(X_train_cat)

    # 数值型变量预处理，
    from sklearn.preprocessing import MinMaxScaler
    mn_X = MinMaxScaler()
    numerical_features = ['temp', 'atemp', 'hum', 'windspeed']
    temp = mn_X.fit_transform(train[numerical_features])
    X_train_num = pd.DataFrame(data=temp, columns=numerical_features, index=train.index)
    #print(X_train_num.head())

    # 合并数据
    X_train = pd.concat([X_train_cat, X_train_num, train['holiday'], train['workingday']], axis=1, ignore_index=False)
    # print(X_train.head())

    # 合并数据
    FE_train = pd.concat([train['instant'], X_train, train['yr'], train['cnt']], axis=1)
    FE_train.to_csv('FE_day.csv', index=False)  # 保存数据
    # print(FE_train.head())

    #print(FE_train.info())
def load_data():  # 导入数据
    global x_data, y_data, name_data

    if not os.path.isfile("FE_day.csv"):  # 调用已经做好特征工程的文件，如果文件不存在，就调用函数生成该文件
        Data_preprocessing()

    data = pd.read_csv("FE_day.csv")

    data = data.drop(['instant', 'hum', 'windspeed'], axis=1)  # 去掉编号、湿度、风速等不相关数据
    ##    print(data)

    y_data = data['cnt']
    x_data = data.drop('cnt', axis=1)

    y_data = np.array(y_data)
    x_data = np.array(x_data)
    name_data = list(data.columns)  # 返回对象列索引

##    print(x_data)
##    print(y_data)
##    print(name_data)
def traintestsplit():  # 数据分割，一部分用于验证、一部分用于训练
    global x_data, y_data, name_data

    X_train, X_test, y_train, y_test = train_test_split(x_data, y_data, random_state=0,
                                                        test_size=0.20)  # 分割数据，20%用于测试，80%用于训练

    return X_train, X_test, y_train, y_test

if __name__ == '__main__':
    load_data()  # 数据导入
    X_train, X_test, y_train, y_test = traintestsplit()  # 数据分割

    print("最小二乘线性回归模型")
    #使用线性回归模型LinearRegression对数据进行训练及预测
    lrg=LinearRegression()#最小二乘线性回归模型
    #使用训练数据进行参数估计
    lrg.fit(X_train,y_train) #训练模型
    #R2评价指标
    y_test_pred_lr = lrg.predict(X_test)
    y_train_pred_lr = lrg.predict(X_train)
    print('The r2 score of RidgeCV on test is', r2_score(y_test, y_test_pred_lr))
    print('The r2 score of RidgeCV on train is', r2_score(y_train, y_train_pred_lr))
    #RMSE评价指标
    Rmse_test=mean_absolute_error(y_test,y_test_pred_lr)
    print("RMSE:{}".format(Rmse_test))


    print("岭回归模型")
    alphas = [0.001, 0.01, 0.1, 1]
    ridge = RidgeCV(alphas=alphas, store_cv_values=True)
    # 训练模型
    ridge.fit(X_train, y_train)
    #R2评价指标
    y_test_pred_ridge = ridge.predict(X_test)
    y_train_pred_ridge = ridge.predict(X_train)
    print('The r2 score of RidgeCV on test is', r2_score(y_test, y_test_pred_ridge))
    print('The r2 score of RidgeCV on train is', r2_score(y_train, y_train_pred_ridge))
    #RMSE评价指标
    Rmse_test=mean_absolute_error(y_test,y_test_pred_lr)
    print("RMSE:{}".format(Rmse_test))


    print("Lasso模型")
    lasso = Lasso()  # Lasso模型
    #使用训练数据进行参数估计
    lasso.fit(X_train,y_train) #训练模型
    #R2评价指标
    y_test_pred_lr = lasso.predict(X_test)
    y_train_pred_lr = lasso.predict(X_train)
    print('The r2 score of RidgeCV on test is', r2_score(y_test, y_test_pred_lr))
    print('The r2 score of RidgeCV on train is', r2_score(y_train, y_train_pred_lr))
    #RMSE评价指标
    Rmse_test=mean_absolute_error(y_test,y_test_pred_lr)
    print("RMSE:{}".format(Rmse_test))


    # 数据视图，此处获取各个算法的训练数据的coef_:系数，coef_可以理解为系数

    plt.figure(figsize=(12, 9))

    # 线性回归 得到的coef
    axes = plt.subplot(221)
    axes.plot(lrg.coef_)
    axes.set_title('lrg_coef')

    # l岭回归 得到的coef
    axes = plt.subplot(222)
    axes.plot(ridge.coef_)
    axes.set_title('ridge_coef')

    # lasso回归 得到的coef
    axes = plt.subplot(223)
    axes.plot(lasso.coef_)
    axes.set_title('lasso_coef')

    plt.show()



